package com.md2ppt.integration;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Python-Java集成桥接器
 * 通过文件和进程通信与Python MD2PPT集成
 */
public class PythonBridge {
    
    private static final Logger logger = LoggerFactory.getLogger(PythonBridge.class);
    private static final String COMMUNICATION_DIR = "temp_communication";
    
    private final ObjectMapper objectMapper;
    private final Path communicationDir;
    
    public PythonBridge() {
        this.objectMapper = new ObjectMapper();
        this.communicationDir = Path.of(COMMUNICATION_DIR);
        initializeCommunicationDirectory();
    }
    
    /**
     * 初始化通信目录
     */
    private void initializeCommunicationDirectory() {
        try {
            if (!Files.exists(communicationDir)) {
                Files.createDirectories(communicationDir);
                logger.info("创建通信目录: {}", communicationDir.toAbsolutePath());
            }
        } catch (IOException e) {
            logger.error("无法创建通信目录", e);
            throw new RuntimeException("通信目录初始化失败", e);
        }
    }
    
    /**
     * 调用Python MD2PPT进行预处理
     */
    public PythonResult invokePythonPreprocessing(String markdownPath, Map<String, Object> options) {
        var requestId = generateRequestId();
        logger.info("调用Python预处理: {}", requestId);
        
        try {
            // 准备请求数据
            var request = new PythonRequest(
                "preprocess",
                markdownPath,
                options,
                requestId
            );
            
            // 写入请求文件
            var requestFile = communicationDir.resolve(requestId + "_request.json");
            writeRequestFile(requestFile, request);
            
            // 调用Python脚本
            var result = executePythonScript("preprocess.py", requestFile);
            
            // 读取响应
            var responseFile = communicationDir.resolve(requestId + "_response.json");
            return readResponseFile(responseFile);
            
        } catch (Exception e) {
            logger.error("Python预处理调用失败", e);
            return new PythonResult(false, "Python调用失败: " + e.getMessage(), null);
        } finally {
            cleanupRequestFiles(requestId);
        }
    }
    
    /**
     * 调用Python生成基础PPT结构
     */
    public PythonResult generateBasePPT(String configPath, String outputPath) {
        var requestId = generateRequestId();
        logger.info("调用Python生成基础PPT: {}", requestId);
        
        try {
            var request = new PythonRequest(
                "generate_base",
                configPath,
                Map.of("output_path", outputPath),
                requestId
            );
            
            var requestFile = communicationDir.resolve(requestId + "_request.json");
            writeRequestFile(requestFile, request);
            
            var result = executePythonScript("generate_base.py", requestFile);
            
            var responseFile = communicationDir.resolve(requestId + "_response.json");
            return readResponseFile(responseFile);
            
        } catch (Exception e) {
            logger.error("Python基础PPT生成失败", e);
            return new PythonResult(false, "基础PPT生成失败: " + e.getMessage(), null);
        } finally {
            cleanupRequestFiles(requestId);
        }
    }
    
    /**
     * 检查Python环境
     */
    public boolean checkPythonEnvironment() {
        try {
            logger.info("检查Python环境");
            
            var process = new ProcessBuilder("python", "-c", 
                "import md2ppt; print('MD2PPT可用')")
                .redirectErrorStream(true)
                .start();
            
            var result = process.waitFor(10, TimeUnit.SECONDS);
            
            if (result && process.exitValue() == 0) {
                logger.info("Python环境检查通过");
                return true;
            } else {
                logger.warn("Python环境检查失败");
                return false;
            }
            
        } catch (Exception e) {
            logger.error("Python环境检查异常", e);
            return false;
        }
    }
    
    /**
     * 执行Python脚本
     */
    private boolean executePythonScript(String scriptName, Path requestFile) throws Exception {
        var command = new String[]{
            "python", 
            "-m", "md2ppt.integration.java_bridge",
            scriptName,
            requestFile.toString()
        };
        
        logger.debug("执行Python命令: {}", String.join(" ", command));
        
        var process = new ProcessBuilder(command)
            .redirectErrorStream(true)
            .start();
        
        var completed = process.waitFor(300, TimeUnit.SECONDS); // 5分钟超时
        
        if (!completed) {
            process.destroyForcibly();
            throw new RuntimeException("Python脚本执行超时");
        }
        
        if (process.exitValue() != 0) {
            var output = new String(process.getInputStream().readAllBytes());
            throw new RuntimeException("Python脚本执行失败: " + output);
        }
        
        return true;
    }
    
    /**
     * 写入请求文件
     */
    private void writeRequestFile(Path requestFile, PythonRequest request) throws IOException {
        var json = objectMapper.writeValueAsString(request);
        Files.writeString(requestFile, json, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
        logger.debug("写入请求文件: {}", requestFile);
    }
    
    /**
     * 读取响应文件
     */
    private PythonResult readResponseFile(Path responseFile) throws IOException {
        // 等待响应文件生成
        var maxWaitTime = 30000; // 30秒
        var waitTime = 0;
        var waitInterval = 500; // 500ms
        
        while (!Files.exists(responseFile) && waitTime < maxWaitTime) {
            try {
                Thread.sleep(waitInterval);
                waitTime += waitInterval;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new IOException("等待响应文件中断", e);
            }
        }
        
        if (!Files.exists(responseFile)) {
            throw new IOException("响应文件未生成: " + responseFile);
        }
        
        var json = Files.readString(responseFile);
        var response = objectMapper.readValue(json, PythonResponse.class);
        
        logger.debug("读取响应文件: {}", responseFile);
        return new PythonResult(response.success(), response.message(), response.data());
    }
    
    /**
     * 清理请求文件
     */
    private void cleanupRequestFiles(String requestId) {
        try {
            var requestFile = communicationDir.resolve(requestId + "_request.json");
            var responseFile = communicationDir.resolve(requestId + "_response.json");
            
            Files.deleteIfExists(requestFile);
            Files.deleteIfExists(responseFile);
            
            logger.debug("清理请求文件: {}", requestId);
        } catch (IOException e) {
            logger.warn("清理请求文件失败: {}", requestId, e);
        }
    }
    
    /**
     * 生成请求ID
     */
    private String generateRequestId() {
        return "req_" + System.currentTimeMillis() + "_" + Thread.currentThread().getId();
    }
    
    /**
     * Python请求数据
     */
    public record PythonRequest(
        String action,
        String inputPath,
        Map<String, Object> options,
        String requestId
    ) {}
    
    /**
     * Python响应数据
     */
    public record PythonResponse(
        boolean success,
        String message,
        Map<String, Object> data
    ) {}
    
    /**
     * Python调用结果
     */
    public record PythonResult(
        boolean success,
        String message,
        Map<String, Object> data
    ) {}
}